package com.wujie.mall.domain.payment.impl;

import com.wujie.mall.domain.payment.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 * 银行卡支付渠道实现
 * 
 * 设计模式应用：工厂方法模式的具体产品
 * 
 * @author wujie
 * @since 2024-08-26
 */
@Slf4j
@Component
public class BankCardChannel implements PaymentChannel {

    private static final String BANK_GATEWAY = "https://gateway.bank.com/payment";
    
    @Override
    public PaymentResponse pay(PaymentRequest request) {
        log.info("开始处理银行卡支付，订单号: {}, 金额: {}", request.getOrderNo(), request.getAmount());
        
        try {
            // 验证请求参数
            validateRequest(request);
            
            // 模拟银行卡支付处理
            String paymentNo = generateBankTradeNo(request.getOrderNo());
            String redirectUrl = buildBankPaymentUrl(request, paymentNo);
            
            log.info("银行卡支付预处理成功，支付单号: {}", paymentNo);
            
            PaymentResponse response = PaymentResponse.success(request.getOrderNo(), paymentNo, redirectUrl);
            response.putExtraData("payment_method", "bank_card");
            response.putExtraData("redirect_url", redirectUrl);
            
            return response;
            
        } catch (Exception e) {
            log.error("银行卡支付处理失败，订单号: {}", request.getOrderNo(), e);
            return PaymentResponse.failure(request.getOrderNo(), "BANK_ERROR", e.getMessage());
        }
    }

    @Override
    public PaymentResponse queryPaymentStatus(String orderNo) {
        log.info("查询银行卡支付状态，订单号: {}", orderNo);
        
        try {
            // 模拟查询银行卡支付状态
            Thread.sleep(120); // 模拟网络延迟（银行系统通常较慢）
            
            // 模拟随机支付状态
            double random = Math.random();
            if (random > 0.6) { // 40%概率支付成功
                String paymentNo = generateBankTradeNo(orderNo);
                PaymentResponse response = PaymentResponse.success(orderNo, paymentNo, null);
                response.putExtraData("bank_code", "CMB"); // 模拟银行代码
                response.putExtraData("card_type", "DEBIT"); // 模拟卡类型
                response.putExtraData("auth_code", generateAuthCode());
                response.putExtraData("settlement_date", LocalDateTime.now().plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                return response;
            } else if (random > 0.2) { // 40%概率处理中
                return PaymentResponse.pending(orderNo, generateBankTradeNo(orderNo));
            } else { // 20%概率失败
                return PaymentResponse.failure(orderNo, "BANK_DECLINE", "银行卡余额不足或交易被拒绝");
            }
            
        } catch (Exception e) {
            log.error("查询银行卡支付状态失败，订单号: {}", orderNo, e);
            return PaymentResponse.failure(orderNo, "QUERY_ERROR", e.getMessage());
        }
    }

    @Override
    public PaymentResponse cancelPayment(String orderNo) {
        log.info("取消银行卡支付，订单号: {}", orderNo);
        
        try {
            // 模拟取消银行卡支付
            Thread.sleep(100); // 模拟网络延迟
            
            PaymentResponse response = PaymentResponse.builder()
                    .success(true)
                    .status(PaymentResponse.PaymentStatus.CANCELLED)
                    .orderNo(orderNo)
                    .responseTime(LocalDateTime.now())
                    .build();
            
            response.putExtraData("cancel_time", LocalDateTime.now().toString());
            response.putExtraData("refund_status", "PROCESSING");
            response.putExtraData("refund_days", "3-5"); // 银行退款通常需要3-5个工作日
            
            log.info("银行卡支付取消成功，订单号: {}", orderNo);
            return response;
            
        } catch (Exception e) {
            log.error("取消银行卡支付失败，订单号: {}", orderNo, e);
            return PaymentResponse.failure(orderNo, "CANCEL_ERROR", e.getMessage());
        }
    }

    @Override
    public PaymentType getPaymentType() {
        return PaymentType.BANK_CARD;
    }

    /**
     * 生成银行交易号
     * @param orderNo 订单号
     * @return 银行交易号
     */
    private String generateBankTradeNo(String orderNo) {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 10);
        return "BANK_" + timestamp + "_" + uuid;
    }

    /**
     * 生成银行授权码
     * @return 授权码
     */
    private String generateAuthCode() {
        return String.valueOf(100000 + (int)(Math.random() * 900000));
    }

    /**
     * 构建银行支付URL
     * @param request 支付请求
     * @param paymentNo 支付单号
     * @return 银行支付URL
     */
    private String buildBankPaymentUrl(PaymentRequest request, String paymentNo) {
        // 在实际应用中，这里会根据银行网关构建真实的支付URL
        StringBuilder url = new StringBuilder();
        url.append(BANK_GATEWAY);
        url.append("?merchantId=M123456789");
        url.append("&orderNo=").append(request.getOrderNo());
        url.append("&amount=").append(request.getAmount());
        url.append("&currency=CNY");
        url.append("&subject=").append(java.net.URLEncoder.encode(request.getSubject(), java.nio.charset.StandardCharsets.UTF_8));
        url.append("&returnUrl=").append(java.net.URLEncoder.encode(request.getReturnUrl(), java.nio.charset.StandardCharsets.UTF_8));
        url.append("&notifyUrl=").append(java.net.URLEncoder.encode(request.getNotifyUrl(), java.nio.charset.StandardCharsets.UTF_8));
        url.append("&timestamp=").append(System.currentTimeMillis());
        url.append("&signature=").append(generateSignature());
        
        return url.toString();
    }

    /**
     * 生成银行支付签名
     * @return 签名
     */
    private String generateSignature() {
        // 在实际应用中，这里会根据银行规则生成真实的签名
        return UUID.randomUUID().toString().replace("-", "").toUpperCase();
    }

    @Override
    public void validateRequest(PaymentRequest request) {
        PaymentChannel.super.validateRequest(request);
        
        // 银行卡支付特有的验证逻辑
        if (request.getSubject() == null || request.getSubject().trim().isEmpty()) {
            throw new IllegalArgumentException("银行卡支付必须提供商品名称");
        }
        
        if (request.getReturnUrl() == null || request.getReturnUrl().trim().isEmpty()) {
            throw new IllegalArgumentException("银行卡支付必须提供同步返回地址");
        }
        
        if (request.getNotifyUrl() == null || request.getNotifyUrl().trim().isEmpty()) {
            throw new IllegalArgumentException("银行卡支付必须提供异步通知地址");
        }
        
        // 银行卡支付金额限制：单笔最小1元，最大20万元
        if (request.getAmount().compareTo(new java.math.BigDecimal("1.00")) < 0) {
            throw new IllegalArgumentException("银行卡支付金额不能小于1元");
        }
        
        if (request.getAmount().compareTo(new java.math.BigDecimal("200000")) > 0) {
            throw new IllegalArgumentException("银行卡支付金额不能超过20万元");
        }
        
        // 检查用户ID
        if (request.getUserId() == null) {
            throw new IllegalArgumentException("银行卡支付必须提供用户ID");
        }
        
        log.debug("银行卡支付请求验证通过，订单号: {}", request.getOrderNo());
    }
}